package com.yangchuang.openpicture.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yangchuang.openpicture.bulider.PictureStatsUpdateBuilder;
import com.yangchuang.openpicture.constant.RedisConstants;
import com.yangchuang.openpicture.constant.UserFavoritePictureRedisConstants;
import com.yangchuang.openpicture.mapper.UserFavoritePictureMapper;
import com.yangchuang.openpicture.pojo.UserFavoritePicture;
import com.yangchuang.openpicture.service.*;
import com.yangchuang.openpicture.util.RedisUtils;
import com.yangchuang.openpicture.util.ShanghaiTimeUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

import static com.yangchuang.openpicture.util.ShanghaiTimeUtils.getCurrentTimeStr;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserFavoritePictureServiceImpl extends ServiceImpl<UserFavoritePictureMapper, UserFavoritePicture> implements UserFavoritePictureService {

    private final RedisUtils redisUtils;
    private final PictureStatisticsService pictureStatisticsService;
    private final PictureService pictureService;
    private final UserStatisticsService userStatisticsService;
    private final UserFavoriteFolderService userFavoriteFolderService;


    @Override
    public boolean hasUserEverFavoritedPicture(Long userId, Long pictureId) {
        return redisUtils.set().contains(RedisConstants.USER_FAVORITE_PICTURE_SET + userId, String.valueOf(pictureId));
    }

    @Override
    public void FavoriteFolderHashInit(Long userId, Long folderId) {
        Map<String, Object> favorite_folder_hash = new HashMap<>();
        //现在的时间
        String currentTimeStr = ShanghaiTimeUtils.getCurrentTimeStr();
        favorite_folder_hash.put(RedisConstants.FAVORITE_FOLDER_HASH_FIELD_CREATE_TIME, currentTimeStr);
        favorite_folder_hash.put(RedisConstants.FAVORITE_FOLDER_HASH_FIELD_UPDATE_TIME, currentTimeStr);
        //喜欢某张图片 状态字段设置为1
        favorite_folder_hash.put(RedisConstants.USER_LIKE_PICTURE_HASH_FIELD_STATUS, 1);
        redisUtils.hash().addBatch(RedisConstants.FAVORITE_FOLDER_HASH + folderId, favorite_folder_hash);
    }

    //多一个收藏夹
    @Override
    public void userFavoritePictureHashInit(Long userId, Long pictureId, Long folderId) {
        Map<String, Object> user_favorite_picture_hash = new HashMap<>();
        //现在的时间
        String currentTimeStr = ShanghaiTimeUtils.getCurrentTimeStr();
        user_favorite_picture_hash.put(RedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_CREATE_TIME, currentTimeStr);
        user_favorite_picture_hash.put(RedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_UPDATE_TIME, currentTimeStr);
        //喜欢某张图片 状态字段设置为1
        user_favorite_picture_hash.put(RedisConstants.USER_LIKE_PICTURE_HASH_FIELD_STATUS, 1);
        //多一个设置收藏夹的动作
        user_favorite_picture_hash.put(RedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_FOLDER_ID, folderId);
        redisUtils.hash().addBatch(RedisConstants.USER_FAVORITE_PICTURE_HASH + userId + ":" + pictureId, user_favorite_picture_hash);
        //对应的收藏夹下面的图片 数量+1 且 设置这个文件夹 用户肯定只能把图片收藏到已经存在的收藏夹
        //这里不用和其它的判断是否存在 因为必须存在
        String key = RedisConstants.FAVORITE_FOLDER_HASH + folderId;
        //更新时间 和 这个文件夹下面的图片的数量 folder_name user_id 和 创建时间 不变
        redisUtils.hash().modifyField(key, RedisConstants.FAVORITE_FOLDER_HASH_FIELD_UPDATE_TIME, currentTimeStr);
        redisUtils.hash().incrBy(key, RedisConstants.FAVORITE_FOLDER_HASH_FIELD_PICTURE_NUMBER, 1);
    }

//    @Override
//    public void toggleFavorite(Long userId, Long pictureId, Long folderId, Boolean isFavorite) {
//        //1.user_favorite_picture的两个结构
//        // set里面 key:user_id   set:收藏的图片的id(支持自动去重，重复的添加不进去) 这里的key直接区分到user级别就可以
//        boolean result = hasUserEverFavoritedPicture(userId, pictureId);
//        //不管这个result是啥 我们都可以把pictureId加进去 因为set支持自动去重 通常这种做法更加推荐
//        redisUtils.set().add(RedisConstants.USER_FAVORITE_PICTURE_SET + userId, String.valueOf(pictureId));
//        String key = RedisConstants.USER_FAVORITE_PICTURE_HASH + userId + ":" + pictureId;
//        //接下来判断是否存在
//        if (result) {
//            //存在 不是第一次 只需要修改几个状态 更新时间的值即可
//            redisUtils.hash().modifyField(key, RedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_STATUS, isFavorite ? 1 : 0);
//            //更新update_time
//            redisUtils.hash().modifyField(key, RedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_UPDATE_TIME, getCurrentTimeStr());
//            //我们这里默认 不允许移动 想要移动 只能取消 然后重新添加收藏
//            //对应收藏夹的状态也要进行更新
//            String folderKey = RedisConstants.FAVORITE_FOLDER_HASH + folderId;
//            //更新时间 和 这个文件夹 下面的图片的数量 folder_name user_id 和 创建时间 不变
//            redisUtils.hash().modifyField(folderKey, RedisConstants.FAVORITE_FOLDER_HASH_FIELD_UPDATE_TIME, getCurrentTimeStr());
//            redisUtils.hash().incrBy(folderKey, RedisConstants.FAVORITE_FOLDER_HASH_FIELD_PICTURE_NUMBER, isFavorite ? 1 : -1);
//        } else {
//            //不存在 第一次 先创建 然后赋值 抽象成一个方法 只能是第一次收藏 不可能是第一次取消收藏
//            userFavoritePictureHashInit(userId, pictureId, folderId);
//        }
//
//        //2.picture_stats结构
//        pictureStatisticsService.PictureStatsHashUpdate(pictureId, null, isFavorite, null, null);
//        //3.根据picture_id 去查出对应的图片主人的id  先去redis  然后mysql  然后添加到redis
//        String ownerId = pictureService.PictureOwnerUpdate(pictureId);
//        //4.维护user_stats结构  现在是用户主动收藏/取消收藏某张 不是被动的
//        new UserStatsUpdateBuilder(userStatisticsService, userId)
//                .setFavorite(isFavorite).setView(true).execute();
//    }


    @Override
    public void toggleFavorite(Long userId, Long pictureId, Long folderId, Boolean isFavorite) {
        //1.user_favorite_picture的两个结构
        // set里面 key:user_id   set:收藏的图片的id(支持自动去重，重复的添加不进去) 这里的key直接区分到user级别就可以
        //不管这个result是啥 我们都可以把pictureId加进去 因为set支持自动去重 通常这种做法更加推荐
        redisUtils.setOps().addMembers(UserFavoritePictureRedisConstants.USER_FAVORITE_PICTURE_SET + userId, pictureId);
        //hash结构： 这里的key要能够选中到 某个用户的具体的某张图片 不能只是用户级别！！
        String key = UserFavoritePictureRedisConstants.USER_FAVORITE_PICTURE_HASH + userId + ":" + pictureId;
        //接下来判断是否存在
        //创建时间
        redisUtils.hashOps().setFieldValueIfAbsent(key, UserFavoritePictureRedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_CREATE_TIME, getCurrentTimeStr());
        //无条件的更新 这里是 user_favorite_picture_hash
        redisUtils.hashOps().setFieldValue(key, UserFavoritePictureRedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_UPDATE_TIME, getCurrentTimeStr());
        //关于状态字段 下面一行 两种情况都能对应
        redisUtils.hashOps().setFieldValue(key, UserFavoritePictureRedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_STATUS, isFavorite ? 1 : 0);
        //关于收藏夹字段
        //第一次 直接设置
        //不是第一次 代表这张图片之前用户收藏/取消收藏过 现在也是直接设置 因为可能收藏到另外一个收藏夹下面了
        //所以说 又可以等价到一行代码了
        redisUtils.hashOps().setFieldValue(key, UserFavoritePictureRedisConstants.USER_FAVORITE_PICTURE_HASH_FIELD_FOLDER_ID, folderId);


        //2.对应的图片的状态需要维护
        new PictureStatsUpdateBuilder(pictureStatisticsService, pictureId)
                .setFavorite(isFavorite).execute();///主动将变化的 pictureId 上报到脏数据集合
        //3.当前的用户的状态
        new UserStatsUpdateBuilder(userStatisticsService, userId)
                .setView(true).setFavorite(isFavorite).execute();///主动将变化的 userId 上报到脏数据集合
        //4.图片的主人的状态
        String ownerID = pictureService.PictureOwnerUpdate(pictureId);
        new UserStatsUpdateBuilder(userStatisticsService, Long.valueOf(ownerID))
                .setViewed(true).setFavorited(isFavorite).execute();///主动将变化的 userId 上报到脏数据集合
    }


/*
*         //todo 上报脏数据 这里存啥呢？？        //这里应该没有需要上报的脏数据
        redisUtils.setOps().addMembers(SyncRedisConstants.USER_FAVORITE_PICTURE_DIRTY_SET, );
        redisUtils.setOps().addMembers(UserStasticsRedisConstants.USER_STATS_DIRTY_SET, String.valueOf(userId));
        //这个key要能够区分到具体的某个收藏夹 级别
        String folderKey = UserFavoritePictureRedisConstants.FAVORITE_FOLDER_HASH + folderId;
        //无脑直接设置创建时间 和 更新时间
        redisUtils.hashOps().setFieldValueIfAbsent(folderKey,
                UserFavoritePictureRedisConstants.FAVORITE_FOLDER_HASH_FIELD_CREATE_TIME, getCurrentTimeStr());
        redisUtils.hashOps().setFieldValue(folderKey, UserFavoritePictureRedisConstants.FAVORITE_FOLDER_HASH_FIELD_UPDATE_TIME, getCurrentTimeStr());
        //文件夹的主人 肯定就是当前登录用户
        //第一次 指定
        //不是第一次 也不会变 所以可以无脑直接再次手动指定
        redisUtils.hashOps().setFieldValue(folderKey, UserFavoritePictureRedisConstants.FAVORITE_FOLDER_HASH_FIELD_USER_ID, userId);
        //图片数量
        //第一次 1=0+1 第一次 isFavorite 肯定是1 所以不会错 且会自动新增这个field
        //不是 +1 -1 其实肯定不是null  不用判断

        redisUtils.hashOps().incrementFieldBy(folderKey, UserFavoritePictureRedisConstants.FAVORITE_FOLDER_HASH_FIELD_PICTURE_NUMBER, isFavorite ? 1 : -1);
        //最后一个 folderName 可能会变?? 直接指定下
        String name = userFavoriteFolderService.FolderNameAndIdUpdate(folderId);
        redisUtils.hashOps().setFieldValue(key,UserFavoritePictureRedisConstants.FAVORITE_FOLDER_HASH_FIELD_FOLDER_NAME,name);
        //todo 还要维护文件夹的相关状态 且 上报脏数据
        //这里应该没有需要上报的脏数据 就算name变了 不应该在这里
*/  //todo  这里需要分离出来 遵循 单一职责 的原理

}
